package com.ly.common.core.config;

import com.ly.common.core.tool.security.config.properties.TokenProperties;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Contact;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.info.License;
import io.swagger.v3.oas.models.security.SecurityRequirement;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.GroupedOpenApi;
import org.springdoc.core.customizers.GlobalOpenApiCustomizer;
import org.springdoc.core.filters.GlobalOpenApiMethodFilter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * Swagger3配置
 *
 * @author luoyun
 */
@Slf4j
@Configuration
@RequiredArgsConstructor
public class Swagger3Config implements WebMvcConfigurer {
    
    private final TokenProperties tokenProperties;

    // 定义不需要注入安全要求的路径集合
    Set<String> excludedPaths = new HashSet<>(Arrays.asList(
            "/sys/randomImage/{key}",
            "/sys/login",
            "/sys/phoneLogin",
            "/sys/mLogin",
            "/sys/sms",
            "/sys/cas/client/validateLogin",
            "/test/**",
            "/sys/thirdLogin/**",
            "/sys/user/register"
            // ,"/emp/**"
    ));

    /**
     * 显示swagger-ui.html文档展示页，还必须注入swagger资源：
     *
     * @param registry
     */
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

    @Bean
    public GlobalOpenApiMethodFilter globalOpenApiMethodFilter() {
        return method -> method.isAnnotationPresent(Operation.class);
    }

    /**
     * 全局添加鉴权参数
     *
     * @return
     */
    @Bean
    public GlobalOpenApiCustomizer globalOpenApiCustomizer() {
        return openApi -> {
            if (openApi.getPaths() != null) {
                openApi.getPaths().forEach((path, pathItem) -> {
                    log.debug("path1111111: {}", path);
                    // 检查当前路径是否在排除列表中
                    boolean flag = excludedPaths.stream()
                            .anyMatch(p -> p.equals(path) || (p.endsWith("**") && path.startsWith(p.substring(0, p.length() - 2))));
                    if (!flag) {
                        // 接口添加鉴权参数
                        pathItem.readOperations()
                                .forEach(n ->
                                        n.addSecurityItem(new SecurityRequirement().addList(tokenProperties.getHeader()))
                                );
                    }
                });
            }
        };
    }

    /**
     * 全局信息配置
     */
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
                .info(new Info()
                        .title("后台服务API接口文档")
                        .version("3.8.0")
                        .contact(new Contact().name("湖北思维信息技术有限公司").url("www.lely.com").email("lely@163.com"))
                        .description("后台API接口")
                        .termsOfService("NO terms of service")
                        .license(new License().name("Apache 2.0").url("http://www.apache.org/licenses/LICENSE-2.0.html")))
                .addSecurityItem(new SecurityRequirement().addList(tokenProperties.getHeader()))
                .components(
                        new Components().addSecuritySchemes(
                                tokenProperties.getHeader(),
                                new SecurityScheme().name(tokenProperties.getHeader()).type(SecurityScheme.Type.HTTP)
                        )
                );
    }

    /**
     * 分组管理
     *
     * @return
     */
    @Bean
    public GroupedOpenApi publicApi() {
        return GroupedOpenApi.builder()
                .group("sys-api")
                .pathsToMatch("/sys/**")
                .packagesToScan("com.ly.system.controller")
                .build();
    }

    @Bean
    public GroupedOpenApi testApi() {
        return GroupedOpenApi.builder()
                .group("test-api")
                .pathsToMatch("/test/**")
                .packagesToScan("com.ly.test.controller")
                .build();
    }

    @Bean
    public GroupedOpenApi empApi() {
        return GroupedOpenApi.builder()
                .group("emp-api")
                .pathsToMatch("/emp/**")
                .packagesToScan("com.ly.emp.controller")
                .build();
    }
}